/*
 * Copyright 2008 Andrej Herich
 * 
 * http://azetclient.yw.sk/
 * http://azetclient.googlecode.com/
 * 
 * This file is part of AzetClient.
 * 
 * AzetClient is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * AzetClient is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with AzetClient.  If not, see <http://www.gnu.org/licenses/>.
 */

package sk.yw.azetclient.gui;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.swing.SwingUtilities;
import org.apache.log4j.Logger;
import sk.yw.azetclient.Main;
import sk.yw.azetclient.managers.MessageThreadManagerEvent;
import sk.yw.azetclient.managers.MessageThreadManagerListener;
import sk.yw.azetclient.model.Buddy;
import sk.yw.azetclient.model.Message;
import sk.yw.azetclient.model.MessageThread;
import sk.yw.azetclient.model.MessageThreadEvent;
import sk.yw.azetclient.model.MessageThreadListener;

/**
 *
 * @author error216
 */
public class ConversationManager
        implements MessageThreadListener, MessageThreadManagerListener {
    
    private static final Logger logger = Logger.getLogger(ConversationManager.class);
    
    private final Set<MessageThread> emptyThreads =
            new HashSet<MessageThread>();
    private final Map<Buddy, ConversationFrame> conversations =
            new HashMap<Buddy, ConversationFrame>();
    
    private Buddy user;
    
    public ConversationManager(Buddy user) {
        if (user == null)
            throw new IllegalArgumentException("Null pointer in user");
        
        this.user = user;
    }

    @Override
    public void threadCreated(MessageThreadManagerEvent event) {
        MessageThread thread = (MessageThread) event.getSubject();
        synchronized (emptyThreads) {
            emptyThreads.add(thread);
            thread.addMessageThreadListener(this);
        }
    }

    @Override
    public void threadOpened(MessageThreadManagerEvent event) {
        final MessageThread thread = (MessageThread) event.getSubject();
        Message message = thread.getLastMessage();
        
        final Buddy buddy;
        if (user.equals(message.getSender())) {
            buddy = Main.getMainFrame().getBuddy(
                    message.getReceiver().getName());
        } else {
            buddy = Main.getMainFrame().getBuddy(
                    message.getSender().getName());
        }
        
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                createConversationPanel(buddy, thread, false);
            }
        });
    }

    @Override
    public void messageAdded(MessageThreadEvent e) {
        final MessageThread thread = (MessageThread) e.getSource();
        
        boolean inEmptyThreads;
        synchronized (emptyThreads) {
            inEmptyThreads = emptyThreads.contains(thread);
        }
        
        if (!inEmptyThreads) return;
        
        final Buddy buddy;
        if (user.equals(e.getMessage().getSender())) {
            buddy = e.getMessage().getReceiver();
        } else {
            buddy = e.getMessage().getSender();
        }
        
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                createConversationPanel(buddy, thread, false);
            }
        });
    }

    @Override
    public void messageChanged(MessageThreadEvent e) {
    }
    
    public void createConversationPanel(Buddy buddy, MessageThread thread,
            boolean focus) {
        thread.removeMessageThreadListener(this);
        
        synchronized (emptyThreads) {
            emptyThreads.remove(thread);
        }
        
        synchronized (conversations) {
            ConversationFrame frame;
            if ((frame = conversations.get(buddy)) == null) {
                frame = new ConversationFrame(this, user, buddy, thread);
                frame.setVisible(true);
                conversations.put(buddy, frame);
                logger.info("Conversation frame for buddy " + buddy.getName() + " created.");
            } else {
                frame.createConversationPanel(thread);
            }
            if (focus) frame.requestFocusOnLastInputTextPane();
        }
    }
    
    public void removeConversationFrame(Buddy buddy) {
        synchronized (conversations) {
            Set<MessageThread> threads =
                    conversations.remove(buddy).getThreads();
            for (MessageThread thread : threads) {
                Main.getMainFrame().closeThread(thread);
            }
        }
        logger.info("Conversation frame for buddy " + buddy.getName() + " removed.");
    }

    @Override
    public void messageRemoved(MessageThreadEvent e) {
    }
    
}
